﻿using System;
using System.Threading;
using System.Threading.Tasks;
using Zo.Logging;

namespace Zo.Events.Default
{
    /// <summary>
    /// 默认事件总线。
    /// </summary>
    public class DefaultEventBus : EventBusBase
    {
        private readonly DefaultEventQueue _eventQueue = new DefaultEventQueue();
        private readonly ILogger _logger;
        private bool _disposed;

        /// <summary>
        /// 初始化默认事件总线。
        /// </summary>
        /// <param name="eventHandlers">事件处理器集合。</param>
        public DefaultEventBus(IEventHandlerExecutor eventHandlerExecutor) :
            base(eventHandlerExecutor)
        {
            _logger = LoggerFactory.Current.Create();

            _eventQueue.EventPushed += EventQueue_EventPushed;

            _logger.LogInfo("DefaultEventBus 创建完成");
        }

        #region 发布

        /// <summary>
        /// 发布。
        /// </summary>
        /// <typeparam name="TEvent">事件类型。</typeparam>
        /// <param name="event">事件。</param>
        /// <returns>事件处理结果。</returns>
        public override IEventResult Publish<TEvent>(TEvent @event)
        {
            return _EventHandlerExecutor.HandleEvent(@event);
        }

        /// <summary>
        /// 发布。
        /// </summary>
        /// <typeparam name="TEvent">事件类型。</typeparam>
        /// <param name="event">事件。</param>
        /// <param name="cancellationToken">取消操作通知。</param>
        /// <returns>事件处理结果。</returns>
        public override Task PublishAsync<TEvent>(TEvent @event, CancellationToken cancellationToken = default)
        {
            return Task.Factory.StartNew(() => _eventQueue.Push(@event));
        }

        private async void EventQueue_EventPushed(object sender, DefaultEventProcessedEventArgs e)
        {
            await _EventHandlerExecutor.HandleEventAsync(e.Event);
        }

        #endregion 发布

        /// <summary>
        /// 订阅。
        /// </summary>
        /// <param name="eventType"></param>
        /// <param name="handlerType"></param>
        public override void OnSubscribe(Type eventType, Type handlerType)
        {
            if (!_EventHandlerExecutor.HandlerRegistered(eventType, handlerType))
            {
                _EventHandlerExecutor.RegisterHandler(eventType, handlerType);
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _eventQueue.EventPushed -= EventQueue_EventPushed;

                    _logger.LogInfo($"DefaultEventBus 已经被 Dispose");
                }

                _disposed = true;
                base.Dispose(disposing);
            }
        }
    }
}